package com.lzm.listendemo.util

import android.content.Context
import android.database.ContentObserver
import android.database.Cursor
import android.net.Uri
import android.os.HandlerThread
import android.provider.MediaStore
import android.os.Build
import android.os.Handler
import java.lang.Exception
import java.util.*

class ScreenShotListener private constructor(mContext: Context?) {
    private val mContext: Context
    private var mInternalObserver: ContentObserver? = null
    private var mExternalObserver: ContentObserver? = null
    private var mHandlerThread: HandlerThread? = null
    private var mHandler: Handler? = null
    private var listener: OnScreenShotListener? = null
    private var lastShot = ""
    fun startListen(listener: OnScreenShotListener?) {
        mHandlerThread = HandlerThread("Screenshot_Observer")
        mHandlerThread!!.start()
        mHandler = Handler(mHandlerThread!!.looper)
        this.listener = listener
        mInternalObserver = MediaContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, mHandler)
        mExternalObserver = MediaContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mHandler)
        mContext.contentResolver.registerContentObserver(
                MediaStore.Images.Media.INTERNAL_CONTENT_URI,
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q,
                mInternalObserver!!
        )
        mContext.contentResolver.registerContentObserver(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q,
                mExternalObserver!!
        )
    }

    fun stopListen() {
        if (mInternalObserver != null) {
            try {
                mContext.contentResolver.unregisterContentObserver(mInternalObserver!!)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            mInternalObserver = null
        }
        if (mExternalObserver != null) {
            try {
                mContext.contentResolver.unregisterContentObserver(mExternalObserver!!)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            mExternalObserver = null
        }
    }

    private fun handleMediaContentChange(contentUri: Uri) {
        var cursor: Cursor? = null
        try {
            cursor = mContext.contentResolver.query(
                    contentUri,
                    MEDIA_PROJECTIONS,
                    null,
                    null,
                    MediaStore.Images.ImageColumns.DATE_ADDED + " desc"
            )
            if (cursor == null) {
                return
            }
            if (!cursor.moveToFirst()) {
                return
            }
            val dataIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
            val dateTakenIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_TAKEN)
            val data = cursor.getString(dataIndex)
            val dateTaken = cursor.getLong(dateTakenIndex)
            handleMediaRowData(data, dateTaken)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            if (cursor != null && !cursor.isClosed) {
                cursor.close()
            }
        }
    }

    private fun handleMediaRowData(data: String, dateTaken: Long) {
        if (checkScreenShot(data, dateTaken)) {
            if (listener != null) {
                listener!!.onShot(data, dateTaken)
            }
        }
    }

    private fun checkScreenShot(dataPic: String, dateTaken: Long): Boolean {
        val data = dataPic.toLowerCase(Locale.ROOT)
        for (keyWork in KEYWORDS) {
            if (data.contains(keyWork) && System.currentTimeMillis() - dateTaken < 1000 && lastShot != data) {
                lastShot = data
                return true
            }
        }
        return false
    }

    private inner class MediaContentObserver(private val mContentUri: Uri, handler: Handler?) : ContentObserver(handler) {
        override fun onChange(selfChange: Boolean) {
            super.onChange(selfChange)
            handleMediaContentChange(mContentUri)
        }
    }

    interface OnScreenShotListener {
        fun onShot(picData: String?, dateTaken: Long)
    }

    companion object {
        private val KEYWORDS = arrayOf("screen", "shot", "capture", "cap", "截图")
        private val MEDIA_PROJECTIONS = arrayOf(
                MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.DATE_TAKEN
        )

        @JvmStatic
        fun newInstance(context: Context?): ScreenShotListener {
            return ScreenShotListener(context)
        }
    }

    init {
        requireNotNull(mContext) { "The Context must not null!" }
        this.mContext = mContext
    }
}